﻿using Autofac;
using Common;
using DBContext;
using EV.EventBus;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZoneLine.Common;
using ZoneLine.Models;
using ZoneLine.Models.PackageModel;
using ZoneLine.Printers;
using ZoneLine.Stations.HStation;

namespace ZoneLine.Stations
{
    public class HOP040Station : WorkStationDBase
    {
        public HOP040Station()
        {
            _logUiChannel = nameof(HOP040Station) + "uilog";
        }

        public void Init(string ip, int port, string startAddr, string endUploadCodeAddr, string endUploadDataAddr, string allowWorkAddr, string printName)
        {
            Ip = ip;
            Port = port;
            _startAddr = startAddr;
            _readLength = 514;
            _printerName = printName;

            EndUpLoadCodeAddr = endUploadCodeAddr;
            EndUpLoadDataAddr = endUploadDataAddr;
            AllowWorkAddr = allowWorkAddr;
            StationRecordData = new HOP040StationResult();
            HeartToPlcAddr = "DB55.18.0";
            PrintRltAddr = "DB55.502";

            WorkDirectionAddr = "DB55.508";

            TaskMaster.Default.AddCycleTask(nameof(HOP040Station), 1, () =>
            {
                var value = (short)Cache.WorkDirection;
                WriteData(WorkDirectionAddr, value);
            }, false, EV.EventBus.CycleTask.TimeBaseEnum._1S);

            _logUiChannel = CurrentStationName + "uilog";
            MessageCenter.Subscribe(nameof(HOP040Station), nameof(HOP040Station), (e) =>
            {
                PrintLabel(false);
                return Task.CompletedTask;
            });
        }

        private string _printerName;

        private short _triggerPrint;
        /// <summary>
        /// 触发打印
        /// </summary>
        public short TriggerPrint
        {
            get { return _triggerPrint; }
            set => SetProperty(ref _triggerPrint, value);
        }

        private int _index;
        /// <summary>
        /// 生产流水号
        /// </summary>
        public int Index
        {
            get { return _index; }
            set => SetProperty(ref _index, value);
        }
        private short _handSignalPrint;

        public short HandSignalPrint
        {
            get { return _handSignalPrint; }
            set { _handSignalPrint = value; }
        }
        /// <summary>
        /// 打印结论plc地址
        /// </summary>
        public string PrintRltAddr { get; set; }

        public string WorkDirectionAddr { get; set; }


        private HOP040StationResult _stationRecordData;

        public HOP040StationResult StationRecordData
        {
            get { return _stationRecordData; }
            set => SetProperty(ref _stationRecordData, value);
        }


        private void PrintLabel(bool needInc = true)
        {
            Index = ProductIndexHelper.GetIndex(Cache.Model,0, Cache.WorkDirection,WorkDirectionEnum.Left, needInc);
            LogWithUi(_logUiChannel, $"在{CurrentStationName}收到打印信息，打印第{Index}号工件");
            IPrinter printer = null;
            var config = ContainerServer.Container.Resolve<PrintConfigTotal>();
            var templatePath = string.Empty;
            switch (Cache.Model)
            {
                case ModelEnum.LX:
                    printer = new LXQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.LxqcConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.LxqcConfig.TemplatePathR;
                    }
                    break;
                case ModelEnum.SQ:
                    printer = new SQQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.Sqqc_Config.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.Sqqc_Config.TemplatePathR;
                    }
                    break;
                case ModelEnum.BQKH:
                    printer = new BQKHPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.BqqcKhConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.BqqcKhConfig.TemplatePathR;
                    }
                    break;
                case ModelEnum.BQLH:
                    printer = new BQLHPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.BqqcLHConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.BqqcLHConfig.TemplatePathR;
                    }
                    break;
                case ModelEnum.WL:
                    printer = new WLQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.WlqcConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.WlqcConfig.TemplatePathR;
                    }
                    break;
                default:
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到不存在对应的模板，打印失败");
                    break;
            }
            if (printer != null)
            {
                try
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}开始打印第【{Index}】工件，模板是【${templatePath}】");
                    var code = printer.PrintLabel(templatePath, _printerName, Index);
                    //打印成功，将数据打印的数据记录到关联表中
                    var printRecord = new AbsPrintResult();
                    printRecord.Brand = Cache.Model.ToString();
                    printRecord.AbsCode = StationRecordData.AbsScanCode;
                    printRecord.Code = code;
                    printRecord.PrintTime = DateTime.Now;
                    var para = StationEnableConfig.GetPara();
                    printRecord.LeftRight = (int)Cache.WorkDirection;
                    _dal.AddModel(printRecord);
                    _dal.UpdateModel<HOP040StationResult>(p => p.AbsScanCode == printRecord.AbsCode, p => new HOP040StationResult { Code = code });
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打印第{Index}工件、工件abs码【{StationRecordData.AbsScanCode}】工件二维码【{code}】完成");

                    WriteData(PrintRltAddr, 1);
                }
                catch (Exception ex)
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打印失败,失败原因{ex.Message}");
                    WriteData(PrintRltAddr, 2);
                }
            }
        }

        protected override void DealData(byte[] content)
        {
            StationRecordData.AbsScanCode = GetPlcString(content, 26);
            StationRecordData.NutScanCode = GetPlcString(content, 58);
            StationRecordData.PartType = GetPlcString(content, 90);
            StationRecordData.Result = GetPlcString(content, 102);
            StationRecordData.TigtenTorque = _client.ByteTransform.TransSingle(content, 114);
            StationRecordData.TigtenAngle = _client.ByteTransform.TransSingle(content, 118);
            StationRecordData.CycleTime = _client.ByteTransform.TransSingle(content, 122);

            StationRecordData.SupportPadScanCode = GetPlcString(content, 150);
            StationRecordData.NutScanCode2 = GetPlcString(content, 214);
            StationRecordData.DustCapScanCode = GetPlcString(content, 278);
            StationRecordData.ComponentScanCode = GetPlcString(content, 246);

            StationRecordData.ThreadLength = _client.ByteTransform.TransSingle(content, 510);

            TriggerPrint = _client.ByteTransform.TransInt16(content, 500);
            HandSignalPrint = _client.ByteTransform.TransInt16(content, 506);

            Logger.Log.Debug($"{_logUiChannel}，StartAddr：{_startAddr}，DealData，ReceiveData 转化前=》{string.Join(" ", content)}");
            Logger.Log.Debug($"{_logUiChannel}，StartAddr：{_startAddr}，DealData，ReceiveData 转化后=》{_client.ByteTransform.TransString(content, Encoding.ASCII)}");
            Logger.Log.Debug($"{_logUiChannel}，StartAddr：{_startAddr}，DealData，HandleData  处理后=》{JsonConvert.SerializeObject(StationRecordData)}");
            //Index = _client.ByteTransform.TransInt16(content, 504);
        }

        protected override void DealWithSignal(string name)
        {
            if (name == nameof(StartUploadCode))
            {
                //todo 上传了条码 这时候验证是否要工作
                if (StartUploadCode)
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位结论验证,条码信息是{StationRecordData.AbsScanCode}");
                    var validataRlt = Validata(CurrentStationName, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位的验证结果是{validataRlt}");
                    var writeRlt = WriteWorkActionToPlc(AllowWorkAddr, validataRlt);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位向下位机下发消息，下发{writeRlt}");
                    return;
                }
                else
                {
                    WriteData(EndUpLoadCodeAddr, false);
                    WriteData(AllowWorkAddr, 0);
                    return;
                }
            }

            if (name == nameof(StartUploadData))
            {
                if (StartUploadData)
                {
                    //todo 上传数据 这时候将数据记录到数据库中
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到记录数据命令");
                    var rlt = RecordData();
                    WriteData(EndUpLoadDataAddr, rlt == 1);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}记录数据完成");
                }
                else
                {
                    WriteData(EndUpLoadDataAddr, false);
                }
            }

            if (name == nameof(TriggerPrint))
            {
                if (TriggerPrint == 1&&HandSignalPrint==0)
                {
                    PrintLabel();
                }
                else
                {
                  //  WriteData(PrintRltAddr, 0);
                }
                return;
            }
        }

        protected override int RecordData()
        {
            var result = new HOP040StationResult()
            {
                AbsScanCode = StationRecordData.AbsScanCode,
                NutScanCode = StationRecordData.NutScanCode,
                StationCode = this.StationCode,
                PartType = StationRecordData.PartType,
                Result = StationRecordData.Result,
                TigtenTorque = StationRecordData.TigtenTorque,
                TigtenAngle = StationRecordData.TigtenAngle,
                CycleTime = StationRecordData.CycleTime,
                ThreadLength = StationRecordData.ThreadLength,
                Code = StationRecordData.Code,
            };
            var writeRlt = false;
            if (_dal.CheckExist<HOP040StationResult>(p => p.AbsScanCode == result.AbsScanCode))
            {
                var beforeRlt = _dal.GetModel<HOP040StationResult>(p => p.AbsScanCode == result.AbsScanCode);
                result.Id = beforeRlt.Id;
                writeRlt = _dal.UpdateModelSuper<HOP040StationResult>(p => p.AbsScanCode == result.AbsScanCode, result);
            }
            else
            {
                writeRlt = _dal.AddModel(result);

            }
            return writeRlt ? 1 : 2;
        }


        protected override WorkActionEnum Validata(string stationName, string code, string[] otherStations = null)
        {
            var currentStationName = stationName;
            var stationIndex = Cache.WorkStationValidationList.IndexOf(currentStationName);
            if (stationIndex == -1)
            {
                return WorkActionEnum.NoEnable;
            }
            if (stationIndex > 0)
            {
                //检测上一个站
                var beforeStationName = Cache.WorkStationValidationList[stationIndex - 1];
                LogWithUi(_logUiChannel, $"在{currentStationName}工位上一个启动的检查工位是{beforeStationName}");
                var checkRlt = CheckCodeExistAndResult(beforeStationName, code);
                LogWithUi(_logUiChannel, $"在{beforeStationName}工位检查{code}的结论是{checkRlt}");
                if (checkRlt == 1)
                {
                    if (otherStations != null)
                    {
                        LogWithUi(_logUiChannel, $"在上个工位{beforeStationName}工位检查{code}的结论是{checkRlt},开始检查校验工位结论");
                        foreach (var otherStation in otherStations)
                        {
                            LogWithUi(_logUiChannel, $"{currentStationName}检查校验工位{otherStation}是否工作");
                            var otherStationResult = CheckCodeExistAndResult(otherStation, code);
                            if (otherStationResult == 1)
                            {
                                LogWithUi(_logUiChannel, $"{currentStationName}检查校验工位{otherStation}工作过，不在本工位进行工作");
                                return WorkActionEnum.WorkOkInCheckStation;
                            }
                        }
                    }
                    LogWithUi(_logUiChannel, $"在上个工位{beforeStationName}工位检查{code}的结论是{checkRlt},开始检查是否在本工位{currentStationName}结论");
                    var currentResult = CheckCodeExistAndResult(currentStationName, code);
                    LogWithUi(_logUiChannel, $"在本工位{currentStationName}工位检查{code}的结论是{currentResult}");
                    if (currentResult == 1)
                    {
                        return WorkActionEnum.HasWorkInCurrent;
                    }
                    else
                    {
                        return WorkActionEnum.StartWork;
                    }
                }
                else if (checkRlt == 2)
                {
                    return WorkActionEnum.WorkNgInBefore;
                }
                else
                {
                    return WorkActionEnum.NotWorkInBefore;
                }
            }
            else
            {
                //检查当前工位
                if (otherStations != null)
                {
                    LogWithUi(_logUiChannel, $"在{currentStationName}工位不存在上个工位，检查并行工位工作结论");

                    foreach (var otherStation in otherStations)
                    {
                        LogWithUi(_logUiChannel, $"{currentStationName}检查校验工位{otherStation}是否工作");
                        var otherStationResult = CheckCodeExistAndResult(otherStation, code);
                        if (otherStationResult == 1)
                        {
                            LogWithUi(_logUiChannel, $"{currentStationName}检查校验工位{otherStation}工作过，不在本工位进行工作");
                            return WorkActionEnum.WorkOkInCheckStation;
                        }
                    }
                }
                LogWithUi(_logUiChannel, $"在{currentStationName}工位不存在上个工位，检查在本工位工作结论");
                var checkResult = CheckCodeExistAndResult(currentStationName, code);
                if (checkResult == 1)
                {
                    return WorkActionEnum.HasWorkInCurrent;

                }
                else
                {
                    return WorkActionEnum.StartWork;
                }
            }
        }
    }
}
